home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Main.bin / MessageDigest.java < prev    next >
Text File  |  1998-09-22  |  12KB  |  389 lines

  1. /*
  2.  * @(#)MessageDigest.java    1.34 98/07/01
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  * 
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.security;
  16.  
  17. import java.util.*;
  18. import java.lang.*;
  19. import java.io.IOException;
  20. import java.io.ByteArrayOutputStream;
  21. import java.io.PrintStream;
  22. import java.io.InputStream;
  23. import java.io.ByteArrayInputStream;
  24.  
  25. /**
  26.  * This MessageDigest class provides the functionality of a message digest
  27.  * algorithm, such as MD5 or SHA. Message digests are secure one-way
  28.  * hash functions that take arbitrary-sized data and output a
  29.  * fixed-length hash value.
  30.  *
  31.  * <p>Like other algorithm-based classes in Java Security, 
  32.  * MessageDigest has two major components:
  33.  *
  34.  * <dl>
  35.  *
  36.  * <dt><b>Message Digest API</b> (Application Program Interface)
  37.  *
  38.  * <dd>This is the interface of methods called by applications needing 
  39.  * message digest services. The API consists of all public methods.
  40.  *
  41.  * <dt><b>Message Digest SPI</b> (Service Provider Interface)
  42.  *
  43.  * <dd>This is the interface implemented by providers that supply
  44.  * specific algorithms. It consists of all methods whose names
  45.  * are prefixed by <em>engine</em>. Each such method is called by    
  46.  * a correspondingly-named public API method. For example,
  47.  * the <code>engineReset</code> method is    
  48.  * called by the <code>reset</code> method.    
  49.  * The SPI methods are abstract; providers must supply a    
  50.  * concrete implementation.
  51.  *
  52.  * </dl>
  53.  *
  54.  * <p>A MessageDigest object starts out initialized. The data is 
  55.  * processed through it using the <a href="#update(byte)">update</a>
  56.  * methods. At any point <a href="#reset">reset</a> can be called
  57.  * to reset the digest. Once all the data to be updated has been
  58.  * updated, one of the <a href="#digest()">digest</a> methods should 
  59.  * be called to complete the hash computation.
  60.  *
  61.  * <p>The <code>digest</code> method can be called once for a given number 
  62.  * of updates. After <code>digest</code> has been called, the MessageDigest
  63.  * object is reset to its initialized state.
  64.  *
  65.  * <p>Implementations are free to implement the Cloneable interface,
  66.  * and doing so will let client applications test cloneability
  67.  * using <code>instanceof Cloneable</code> before cloning: <p>    
  68.  *
  69.  * <pre>
  70.  * MessageDigest md = MessageDigest.getInstance("SHA");
  71.  *
  72.  * if (md instanceof Cloneable) {
  73.  *     md.update(toChapter1);
  74.  *     MessageDigest tc1 = md.clone();
  75.  *     byte[] toChapter1Digest = tc1.digest;
  76.  *     md.update(toChapter2);
  77.  *     ...etc.
  78.  * } else {
  79.  *     throw new DigestException("couldn't make digest of partial content");
  80.  * }
  81.  * </pre>
  82.  *
  83.  * <p>Note that if a given implementation is not cloneable, it is
  84.  * still possible to compute intermediate digests by instantiating
  85.  * several instances, if the number of digests is known in advance.
  86.  *
  87.  * @see DigestInputStream
  88.  * @see DigestOutputStream
  89.  *
  90.  * @version 1.31 97/02/03
  91.  * @author Benjamin Renaud 
  92.  */
  93. public abstract class MessageDigest {
  94.  
  95.     /* Are we in debugging mode? */
  96.     private static boolean debug = false;
  97.  
  98.     /* The digest bits, if any. */
  99.     private byte[] digestBits;
  100.  
  101.     private String algorithm;
  102.  
  103.     /**
  104.      * Creates a message digest with the specified algorithm name.
  105.      * 
  106.      * @param algorithm the standard name of the digest algorithm. 
  107.      * See Appendix A in the <a href=
  108.      * "../guide/security/CryptoSpec.html#AppA">
  109.      * Java Cryptography Architecture API Specification & Reference </a> 
  110.      * for information about standard algorithm names.
  111.      */
  112.     protected MessageDigest(String algorithm) {
  113.     this.algorithm = algorithm;
  114.     }
  115.  
  116.     /**
  117.      * Generates a MessageDigest object that implements the specified digest
  118.      * algorithm. If the default provider package contains a MessageDigest
  119.      * subclass implementing the algorithm, an instance of that subclass
  120.      * is returned. If the algorithm is not available in the default 
  121.      * package, other packages are searched.
  122.      *
  123.      * @param algorithm the name of the algorithm requested. 
  124.      * See Appendix A in the <a href=
  125.      * "../guide/security/CryptoSpec.html#AppA">
  126.      * Java Cryptography Architecture API Specification & Reference </a> 
  127.      * for information about standard algorithm names.
  128.      *
  129.      * @return a Message Digest object implementing the specified
  130.      * algorithm.
  131.      *
  132.      * @exception NoSuchAlgorithmException if the algorithm is
  133.      * not available in the caller's environment.  
  134.      */
  135.     public static MessageDigest getInstance(String algorithm) 
  136.     throws NoSuchAlgorithmException { 
  137.     try {
  138.         return (MessageDigest)Security.getImpl(algorithm, 
  139.                            "MessageDigest", null);
  140.     } catch(NoSuchProviderException e) {
  141.         throw new InternalError("please send a bug report via " +
  142.                     System.getProperty("java.vendor.url.bug"));
  143.     }
  144.     }
  145.  
  146.     /**
  147.      * Generates a MessageDigest object implementing the specified
  148.      * algorithm, as supplied from the specified provider, if such an 
  149.      * algorithm is available from the provider.
  150.      *
  151.      * @param algorithm the name of the algorithm requested. 
  152.      * See Appendix A in the <a href=
  153.      * "../guide/security/CryptoSpec.html#AppA">
  154.      * Java Cryptography Architecture API Specification & Reference </a> 
  155.      * for information about standard algorithm names.
  156.      *
  157.      * @param provider the name of the provider.
  158.      *
  159.      * @return a Message Digest object implementing the specified
  160.      * algorithm.
  161.      *
  162.      * @exception NoSuchAlgorithmException if the algorithm is
  163.      * not available in the package supplied by the requested
  164.      * provider.
  165.      *
  166.      * @exception NoSuchProviderException if the provider is not
  167.      * available in the environment. 
  168.      * 
  169.      * @see Provider 
  170.      */
  171.     public static MessageDigest getInstance(String algorithm, String provider)
  172.     throws NoSuchAlgorithmException, NoSuchProviderException {
  173.     return (MessageDigest)Security.getImpl(algorithm, 
  174.                            "MessageDigest", provider);
  175.     }
  176.  
  177.     /**
  178.      * Updates the digest using the specified byte.    
  179.      * 
  180.      * @param input the byte with which to update the digest.
  181.      */
  182.     public void update(byte input) {
  183.     engineUpdate(input);
  184.     }
  185.  
  186.  
  187.     /**
  188.      * Updates the digest using the specified array of bytes, starting
  189.      * at the specified offset.
  190.      * 
  191.      * @param input the array of bytes.
  192.      *
  193.      * @param offset the offset to start from in the array of bytes.
  194.      *
  195.      * @param len the number of bytes to use, starting at 
  196.      * <code>offset</code>.  
  197.      */
  198.     public void update(byte[] input, int offset, int len) {
  199.     engineUpdate(input, offset, len);
  200.     }
  201.  
  202.     /**
  203.      * Updates the digest using the specified array of bytes.
  204.      * 
  205.      * @param input the array of bytes.
  206.      */
  207.     public void update(byte[] input) {
  208.     engineUpdate(input, 0, input.length);
  209.     }
  210.  
  211.     /**
  212.      * Completes the hash computation by performing final operations
  213.      * such as padding. The digest is reset after this call is made.
  214.      *
  215.      * @return the array of bytes for the resulting hash value.  
  216.      */
  217.     public byte[] digest() {
  218.     /* Resetting is the responsibility of implementors. */
  219.     digestBits = engineDigest();
  220.     return digestBits;
  221.     }
  222.  
  223.     /**
  224.      * Performs a final update on the digest using the specified array 
  225.      * of bytes, then completes the digest computation. That is, this
  226.      * method first calls <a href = "#update(byte[])">update</a> on the
  227.      * array, then calls <a href = "#digest()">digest()</a>.
  228.      *
  229.      * @param input the input to be updated before the digest is
  230.      * completed.
  231.      *
  232.      * @return the array of bytes for the resulting hash value.  
  233.      */
  234.     public byte[] digest(byte[] input) {
  235.     update(input);
  236.     return digest();
  237.     }
  238.  
  239.     /**
  240.      * Helper function that prints unsigned two character hex digits.
  241.      */
  242.     private static void hexDigit(PrintStream p, byte x) {
  243.     char c;
  244.     
  245.     c = (char) ((x >> 4) & 0xf);
  246.     if (c > 9) {
  247.         c = (char) ((c - 10) + 'a');
  248.     } else {
  249.         c = (char) (c + '0');
  250.     }
  251.     p.write(c);
  252.  
  253.     c = (char) (x & 0xf);
  254.     if (c > 9) {
  255.         c = (char)((c - 10) + 'a');
  256.     } else {
  257.         c = (char)(c + '0');
  258.     }
  259.     p.write(c);
  260.     }
  261.  
  262.     /**
  263.      * Returns a string representation of this message digest object.  
  264.      */
  265.     public String toString() {
  266.     ByteArrayOutputStream ou = new ByteArrayOutputStream();
  267.     PrintStream p = new PrintStream(ou);
  268.         
  269.     p.print(this.getClass().getName()+" Message Digest ");
  270.     if (digestBits != null) {
  271.         p.print("<");
  272.         for(int i = 0; i < digestBits.length; i++)
  273.              hexDigit(p, digestBits[i]);
  274.         p.print(">");
  275.     } else {
  276.         p.print("<incomplete>");
  277.     }
  278.     p.println();
  279.     return (ou.toString());
  280.     }
  281.  
  282.     /**
  283.      * Compares two digests for equality. Does a simple byte compare.
  284.      * 
  285.      * @param digesta one of the digests to compare.
  286.      * 
  287.      * @param digestb the other digest to compare.    
  288.      *
  289.      * @return true if the digests are equal, false otherwise.
  290.      */
  291.     public static boolean isEqual(byte digesta[], byte digestb[]) {
  292.     int    i;
  293.         
  294.     if (digesta.length != digestb.length)
  295.         return false;
  296.  
  297.     for (i = 0; i < digesta.length; i++) {
  298.         if (digesta[i] != digestb[i]) {
  299.         return false;
  300.         }
  301.     }
  302.     return true;
  303.     }
  304.  
  305.     /**
  306.      * Resets the digest for further use.
  307.      */
  308.     public void reset() {
  309.     engineReset();
  310.     digestBits = null;
  311.     }
  312.  
  313.     /** 
  314.      * Returns a string that identifies the algorithm, independent of
  315.      * implementation details. The name should be a standard
  316.      * Java Security name (such as "SHA", "MD5", and so on). 
  317.      * See Appendix A in the <a href=
  318.      * "../guide/security/CryptoSpec.html#AppA">
  319.      * Java Cryptography Architecture API Specification & Reference </a> 
  320.      * for information about standard algorithm names.
  321.      */
  322.     public final String getAlgorithm() {
  323.     return algorithm;
  324.     }
  325.  
  326.     /**
  327.      * <b>SPI</b>: Updates the digest using the specified byte.
  328.      *
  329.      * @param input the byte to use for the update.
  330.      */
  331.     protected abstract void engineUpdate(byte input);
  332.  
  333.     /**
  334.      * <b>SPI</b>: Updates the digest using the specified array of bytes,    
  335.      * starting at the specified offset. This should be a no-op if
  336.      * the digest has been finalized.
  337.      *
  338.      * @param input the array of bytes to use for the update.
  339.      *
  340.      * @param offset the offset to start from in the array of bytes.
  341.      *
  342.      * @param len the number of bytes to use, starting at 
  343.      * <code>offset</code>.
  344.      */
  345.     protected abstract void engineUpdate(byte[] input, int offset, int len);
  346.  
  347.     /**
  348.      * <b>SPI</b>: Completes the hash computation by performing final
  349.      * operations such as padding. Once <code>engineDigest</code> has 
  350.      * been called, the engine should be reset (see <a href =
  351.      * "#reset">reset</a>).  Resetting is the responsibility of the
  352.      * engine implementor.
  353.      *
  354.      * @return the array of bytes for the resulting hash value.  
  355.      */
  356.     protected abstract byte[] engineDigest();
  357.  
  358.     /**
  359.      * <b>SPI</b>: Resets the digest for further use.
  360.      */
  361.     protected abstract void engineReset();    
  362.  
  363.  
  364.     /**    
  365.      * Returns a clone if the implementation is cloneable.    
  366.      * 
  367.      * @return a clone if the implementation is cloneable.
  368.      *
  369.      * @exception CloneNotSupportedException if this is called on an
  370.      * implementation that does not support <code>Cloneable</code>.
  371.      */
  372.     public Object clone() throws CloneNotSupportedException {
  373.     if (this instanceof Cloneable) {
  374.         return super.clone();
  375.     } else {
  376.         throw new CloneNotSupportedException();
  377.     }
  378.     }
  379.   
  380.  
  381.     private void debug(String statement) {
  382.     if (debug) {
  383.         System.err.println(statement);
  384.     }
  385.     }
  386.  
  387.  
  388. }
  389.